﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace DataMonitoringOrPlayBack
{
    /// <summary>
    /// 公共变量和函数
    /// </summary>
    public static class CSource
    {
        private static Mutex mutqlst = new Mutex();
        private static Queue<double[]> _queueList = new Queue<double[]>();
        /// <summary>
        /// 光谱
        /// </summary>
        public static double[] dSpectrum
        {
            get
            {
                double[] _d = new double[256];
                mutqlst.WaitOne();
                if (_queueList.Count == 0)
                {
                    mutqlst.ReleaseMutex();
                    return _d;
                }
                _d = _queueList.Dequeue();
                mutqlst.ReleaseMutex();
                return _d;
            }
            set
            {
                mutqlst.WaitOne();
                if (_queueList.Count > 9)
                {
                    _queueList.Dequeue();
                }
                _queueList.Enqueue(value);
                mutqlst.ReleaseMutex();
            }
        }

        public static Mutex mutqlong = new Mutex();
        public static Dictionary<long, long> _lIndexDir = new Dictionary<long, long>(1024 * 1024);
        //public static Queue<long> _Quelong = new Queue<long>(1024 * 1024);
        public static string strDirPath = "D:\\";

        public static Mutex mutqwavsrc = new Mutex();
        public static Queue<Queue<double[]>> _queWavSource = new Queue<Queue<double[]>>(40 * 1024 * 1024);

        //光谱高斯处理后台解析
        public static string strTmpPath = string.Empty;
        public static Queue<long> wavQIndex = new Queue<long>(7200);

        public static long lCount = 0;
        public static Mutex mutsavesource = new Mutex();

        public static Mutex mut = new Mutex();
        //当前文件名
        public static string strCurPath = string.Empty;

        #region//获取波长值
        private static double A = 1570.398804;
        private static double B1 = -0.1617357432842254600000000;
        private static double B2 = -0.0000663390237605199220000;
        private static double B3 = -0.0000000354414062542218740;
        private static double B4 = 0.0000000001906033247900396;
        private static double B5 = -0.0000000000003401445791695;
        private static double[] PreWav = new double[32];

        public static void GetWavesLength(double[] Spectra, ref double[] wavelength)
        {
            int fbgNo = 0;
            GetWavesLength(Spectra, ref wavelength, ref fbgNo);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Spectra"></param>
        /// <param name="wavelength"></param>
        /// <param name="fbgNo"></param>
        public static void GetWavesLength(double[] Spectra, ref double[] wavelength, ref int fbgNo)
        {
            List<double> lstwav = new List<double>();
            fbgNo = 0;
            int iCount = 0;
            double[] _x = new double[256], _y = new double[256];
            for (int i = 0; i < Spectra.Length; i++)
            {
                if (Spectra[i] > 0)
                {
                    _x[iCount] = i;
                    //_y[iCount++] = Math.Log(Spectra[i]);
                    _y[iCount++] = Math.Pow(Spectra[i], 2);
                }
                else if (iCount > 0)
                {
                    if (iCount > 2)
                    {
                        double[] _tx = new double[iCount];
                        double[] _ty = new double[iCount];
                        while (iCount-- > 0)
                        {
                            _tx[iCount] = _x[iCount];
                            _ty[iCount] = _y[iCount];
                        }
                        //PreWav[fbgNo] = _wavlen(_tx, _ty);
                        PreWav[fbgNo] = (PreWav[fbgNo] > 0) ? Avrdouble(PreWav[fbgNo], _wavlen(_tx, _ty)) : _wavlen(_tx, _ty);
                        if (PreWav[fbgNo] < 1525 || PreWav[fbgNo] > 1570)
                        {
                            continue;
                        }
                        lstwav.Add(Math.Round(PreWav[fbgNo++], 5));
                    }
                    _x = new double[256];
                    _y = new double[256];
                    iCount = 0;
                }
            }
            lstwav.Sort();
            wavelength = lstwav.ToArray();
        }
        private static double Avrdouble(double _dpre, double _d)
        {
            double _t = Math.Abs(Math.Floor((_d - _dpre) * 1000d));
            if (_t < 180) return _d;
            if (_t < 250) return _dpre;
            return 0.25d * _d + 0.75d * _dpre;
        }

        /// <summary>
        /// 通过高斯拟合（最小二乘法求参数）求出波长值
        /// </summary>
        /// <param name="_X">因子</param>
        /// <param name="_Y">因子</param>
        /// <returns>波长值</returns>
        private static double _wavlen(double[] _X, double[] _Y)
        {
            if (_X.Length != _Y.Length || _Y.Length < 3)
            {
                return 0;
            }
            try
            {
                double s00 = 0, s10 = 0, s20 = 0, s30 = 0, s40 = 0, s01 = 0, s11 = 0, s21 = 0;
                for (int i = 0; i < _X.Length; i++)
                {
                    s00 += 1;//sigma x^0*y^0;
                    s10 += _X[i];//sigma x;   
                    s20 += Math.Pow(_X[i], 2);//sigma x^2;
                    s30 += Math.Pow(_X[i], 3);//sigma x^3;
                    s40 += Math.Pow(_X[i], 4);//sigma x^4
                    s01 += _Y[i]; //sigma y;
                    s11 += _X[i] * _Y[i]; //sigma x*y;
                    s21 += _X[i] * _X[i] * _Y[i];//sigma x^2*y;
                }
                double tmp = 0.5d * (s21 * (s20 * s10 - s30 * s00) + s11 * (s40 * s00 - s20 * s20) + s01 * (s30 * s20 - s40 * s10))
                            /
                            (s21 * (s10 * s10 - s20 * s00) + s11 * (s30 * s00 - s20 * s10) + s01 * (s20 * s20 - s30 * s10));

                return (A + B1 * tmp + B2 * Math.Pow(tmp, 2) + B3 * Math.Pow(tmp, 3) + B4 * Math.Pow(tmp, 4) + B5 * Math.Pow(tmp, 5));
            }
            catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.StackTrace + ":" + ex.Message); }
            return 0;
        }
        #endregion
        /*
        #region//读取设置传感器分组信息
        public static Dictionary<string, string> SensorGroup = new Dictionary<string, string>();
        public static void ReadXML(string strXML="SensorGroupConfig.xml")
        {
            if ((!File.Exists(strXML)) && (!File.Exists(Environment.CurrentDirectory + "\\" + strXML)))
            {
                frmProperty frm = new frmProperty();
                frm.ShowDialog();                
            }
            // 读取xml配置文件
            //初始化区间及传感器参数
            try
            {
                //文件存在则开始读取
                XmlDocument xmlDoc = new XmlDocument();

                xmlDoc.Load(strXML);
                XmlNode xmlroot = xmlDoc.SelectSingleNode("root");
                //读取分组信息
                XmlNodeList xmlgroups = xmlroot.SelectNodes("Group");
                
                foreach (XmlNode n in xmlgroups)
                {
                    XmlElement xe = (XmlElement)n;

                }

                string pt = "";
                int iSub = 0;

                foreach (XmlNode n in xmlSersors)
                {
                    xe = (XmlElement)n;
                    if (xe.GetAttribute("type") == "1")     //类型为1 指应力传感器
                    {
                        pt = xe.SelectSingleNode("position").InnerText.Trim();   //判断位置，是A点还是B点
                        if (pt == string.Empty) continue;
                        if (pt.StartsWith(ZONE_A_CODE))  //是A点
                        {
                            //取位置序号
                            iSub = int.Parse(pt.Substring(ZONE_A_CODE.Length));
                            if (iSub <= zone.A.Length)
                            {
                                zone.A[iSub - 1].Position = pt;
                                zone.A[iSub - 1].Id = xe.GetAttribute("id");
                                zone.A[iSub - 1].BaseWavelength = double.Parse(xe.SelectSingleNode("base").InnerText);
                                zone.A[iSub - 1].WavelengthScope = double.Parse(xe.SelectSingleNode("scope").InnerText);
                                zone.A[iSub - 1].LimitValue = double.Parse(xe.SelectSingleNode("limit").InnerText);
                            }
                        }
                        else
                        {
                            //取位置序号
                            iSub = int.Parse(pt.Substring(ZONE_B_CODE.Length));
                            if (iSub <= zone.B.Length)
                            {
                                zone.B[iSub - 1].Position = pt;
                                zone.B[iSub - 1].Id = xe.GetAttribute("id");
                                zone.B[iSub - 1].BaseWavelength = double.Parse(xe.SelectSingleNode("base").InnerText);
                                zone.B[iSub - 1].WavelengthScope = double.Parse(xe.SelectSingleNode("scope").InnerText);
                                zone.B[iSub - 1].LimitValue = double.Parse(xe.SelectSingleNode("limit").InnerText);
                            }
                        }

                    }
                    else        //温度传感器
                    {
                        pt = xe.SelectSingleNode("position").InnerText.Trim();   //判断位置，是B点还是道旁盒子
                        if (pt == string.Empty) continue;
                        //取位置序号
                        iSub = int.Parse(pt.Substring(TEMPERATURE.Length));
                        if (iSub <= zone.T.Length)
                        {
                            zone.T[iSub - 1].Position = pt;
                            zone.T[iSub - 1].Id = xe.GetAttribute("id");
                            zone.T[iSub - 1].BaseWavelength = double.Parse(xe.SelectSingleNode("base").InnerText);
                            zone.T[iSub - 1].WavelengthScope = double.Parse(xe.SelectSingleNode("scope").InnerText);
                            zone.T[iSub - 1].LimitValue = double.Parse(xe.SelectSingleNode("limit").InnerText);
                        }
                    }
                }
                //读取通道号
                XmlNode xmlchannalcode = xmlroot.SelectSingleNode("channalcode");
                channalcode = int.Parse(xmlchannalcode.SelectSingleNode("curcode").InnerText);
            }
            catch { }
        }
        public void SaveConfig()
        {
            // 读取xml配置文件
            //初始化区间及传感器参数
            try
            {
                //检测文件是否存在，不存在抛出异常

                //文件存在则开始读取
                XmlDocument xmlDoc = new XmlDocument();

                //创建根节点
                XmlElement xmlRoot = xmlDoc.CreateElement("root");
                xmlDoc.AppendChild(xmlRoot);

                //创建解调仪节点
                XmlElement xmlModem = xmlDoc.CreateElement("modem");
                XmlElement xmlIp = xmlDoc.CreateElement("ip");
                xmlIp.InnerText = modem.Ip;
                xmlModem.AppendChild(xmlIp);
                XmlElement xmlPort = xmlDoc.CreateElement("port");
                xmlPort.InnerText = modem.Port.ToString();
                xmlModem.AppendChild(xmlPort);
                xmlRoot.AppendChild(xmlModem);

                //创建转发目的机器参数
                XmlElement xmlRelay = xmlDoc.CreateElement("relay");
                XmlElement xmlIp1 = xmlDoc.CreateElement("ip");
                xmlIp1.InnerText = relay.Ip;
                xmlRelay.AppendChild(xmlIp1);
                XmlElement xmlPort1 = xmlDoc.CreateElement("port");
                xmlPort1.InnerText = relay.Port.ToString();
                xmlRelay.AppendChild(xmlPort1);
                xmlRoot.AppendChild(xmlRelay);

                //创建核心板参数
                XmlElement xmlCoreBoard = xmlDoc.CreateElement("coreboard");
                XmlElement xmlReceivePort = xmlDoc.CreateElement("receive_port");
                xmlReceivePort.InnerText = coreboard.ReceivePort.ToString();
                xmlCoreBoard.AppendChild(xmlReceivePort);

                XmlElement xmlSendPort = xmlDoc.CreateElement("send_port");
                xmlSendPort.InnerText = coreboard.SendPort.ToString();
                xmlCoreBoard.AppendChild(xmlSendPort);

                XmlElement xmlDesIP = xmlDoc.CreateElement("des_ip");
                xmlDesIP.InnerText = coreboard.DestinationIp;
                xmlCoreBoard.AppendChild(xmlDesIP);

                XmlElement xmlLocIP = xmlDoc.CreateElement("scr_ip");
                xmlLocIP.InnerText = coreboard.LocalIp;
                xmlCoreBoard.AppendChild(xmlLocIP);
                xmlRoot.AppendChild(xmlCoreBoard);


                //创建区间及传感器参数(含温度)
                XmlElement xmlZone = xmlDoc.CreateElement("zone");
                xmlZone.SetAttribute("id", zone.Id);
                xmlZone.SetAttribute("name", zone.Name);
                xmlZone.SetAttribute("checknum", zone.CheckNum.ToString());

                for (int i = 0; i < zone.A.Length; i++)
                {
                    XmlElement xmlA = xmlDoc.CreateElement("sensor");
                    xmlA.SetAttribute("id", zone.A[i].Id);
                    xmlA.SetAttribute("type", zone.A[i].Type.ToString());

                    XmlElement xmlPosition = xmlDoc.CreateElement("position");
                    xmlPosition.InnerText = zone.A[i].Position;
                    XmlElement xmlBase = xmlDoc.CreateElement("base");
                    xmlBase.InnerText = zone.A[i].BaseWavelength.ToString();
                    XmlElement xmlScope = xmlDoc.CreateElement("scope");
                    xmlScope.InnerText = zone.A[i].WavelengthScope.ToString();
                    XmlElement xmlLimit = xmlDoc.CreateElement("limit");
                    xmlLimit.InnerText = zone.A[i].LimitValue.ToString();

                    xmlA.AppendChild(xmlPosition);
                    xmlA.AppendChild(xmlBase);
                    xmlA.AppendChild(xmlScope);
                    xmlA.AppendChild(xmlLimit);
                    xmlZone.AppendChild(xmlA);

                }

                for (int i = 0; i < zone.B.Length; i++)
                {
                    XmlElement xmlB = xmlDoc.CreateElement("sensor");
                    xmlB.SetAttribute("id", zone.B[i].Id);
                    xmlB.SetAttribute("type", zone.B[i].Type.ToString());

                    XmlElement xmlPosition = xmlDoc.CreateElement("position");
                    xmlPosition.InnerText = zone.B[i].Position;
                    XmlElement xmlBase = xmlDoc.CreateElement("base");
                    xmlBase.InnerText = zone.B[i].BaseWavelength.ToString();
                    XmlElement xmlScope = xmlDoc.CreateElement("scope");
                    xmlScope.InnerText = zone.B[i].WavelengthScope.ToString();
                    XmlElement xmlLimit = xmlDoc.CreateElement("limit");
                    xmlLimit.InnerText = zone.B[i].LimitValue.ToString();

                    xmlB.AppendChild(xmlPosition);
                    xmlB.AppendChild(xmlBase);
                    xmlB.AppendChild(xmlScope);
                    xmlB.AppendChild(xmlLimit);
                    xmlZone.AppendChild(xmlB);

                }

                for (int i = 0; i < zone.T.Length; i++)
                {
                    XmlElement xmlT = xmlDoc.CreateElement("sensor");
                    xmlT.SetAttribute("id", zone.T[i].Id);
                    xmlT.SetAttribute("type", zone.T[i].Type.ToString());

                    XmlElement xmlPosition = xmlDoc.CreateElement("position");
                    xmlPosition.InnerText = zone.T[i].Position;
                    XmlElement xmlBase = xmlDoc.CreateElement("base");
                    xmlBase.InnerText = zone.T[i].BaseWavelength.ToString();
                    XmlElement xmlScope = xmlDoc.CreateElement("scope");
                    xmlScope.InnerText = zone.T[i].WavelengthScope.ToString();
                    XmlElement xmlLimit = xmlDoc.CreateElement("limit");
                    xmlLimit.InnerText = zone.T[i].LimitValue.ToString();

                    xmlT.AppendChild(xmlPosition);
                    xmlT.AppendChild(xmlBase);
                    xmlT.AppendChild(xmlScope);
                    xmlT.AppendChild(xmlLimit);
                    xmlZone.AppendChild(xmlT);

                }
                xmlRoot.AppendChild(xmlZone);

                //创建解调仪通道号的参数
                XmlElement xmlChannalcode = xmlDoc.CreateElement("channalcode");
                XmlElement xmlcurcode = xmlDoc.CreateElement("curcode");
                xmlcurcode.InnerText = channalcode.ToString();
                xmlChannalcode.AppendChild(xmlcurcode);
                xmlRoot.AppendChild(xmlChannalcode);

                xmlDoc.Save(xmlfile);

            }
            catch (Exception ex) { File.AppendAllText(Application.StartupPath + "\\Eor.log", string.Format("{0}  {1}:{2}\r\n", DateTime.Now, ex.StackTrace, ex.Message)); }
        }
        #endregion
        */
    }

    /// <summary>
    /// 均值滤波
    /// </summary>
    public class FilterAvg
    {
        private double[] dValues = null;
        private int iCount = 0;
        private int iLen = 0;
        private double _dValue = 0;

        public FilterAvg(int iAvgCount)
        {
            iCount = iAvgCount;
            dValues = new double[iCount];
            iLen = 0;
            _dValue = 0;
        }
        public double AppendValue(double V)
        {
            double ret = 0;
            if (iLen < iCount) iLen++;
            for (int i = dValues.Length - iLen; i < dValues.Length - 1; i++)
            {
                dValues[i] = dValues[i + 1];
                ret += dValues[i];
            }
            dValues[dValues.Length - 1] = V;
            _dValue = (ret + V) / iLen;
            return _dValue;
        }

        public void Reset()
        {
            iLen = 0;
            _dValue = 0;
        }
        public double dValue
        {
            get { return _dValue; }
        }
    }
    /// <summary>
    /// 带通滤波
    /// </summary>
    public class FilterWidth
    {
        private double dWidth = 0;
        private double dMin = 0;
        private double dMax = 0;
        private bool bHadValue = false;
        private double _dValue = 0;

        public FilterWidth(double dFilterWidth)
        {
            dWidth = dFilterWidth;
            dMin = 0;
            dMax = 0;
            bHadValue = false;
        }
        public double AppendValue(double V)
        {
            if (bHadValue)
            {
                if (V < dMin)
                {
                    if (dMax - V > dWidth)
                    {
                        dMax = dMin;
                        dMin = V;
                    }
                }
                else
                {
                    if (V > dMax)
                    {
                        if (V - dMin > dWidth)
                        {
                            dMin = dMax;
                            dMax = V;
                        }
                    }
                }
            }
            else
            {
                dMin = V;
                dMax = V;
                bHadValue = true;
            }

            _dValue = (dMax + dMin) / 2;
            return _dValue;
        }
        public void Reset()
        {
            dMin = 0;
            dMax = 0;
            bHadValue = false;
        }
        public double dValue
        {
            get { return _dValue; }
        }
    }
    /// <summary>
    /// 寻峰算法
    /// </summary>
    public class FinderMax
    {
        enum Status { stUp, stDown, stNone }
        private int _iCount = 0;
        private double dLastValue = 0;
        private bool bHadValue = false;
        private double V1 = 0, V2 = 0, V3 = 0;
        private double dSeed = 0;

        private Status _status = Status.stNone;

        public FinderMax(double Seed)
        {
            dSeed = Seed;
            _status = Status.stNone;
            dLastValue = 0;
            _iCount = 0;
            V1 = 0;
            V2 = 0;
            V3 = 0;
        }

        public bool AppendValue(double V)
        {
            Boolean ret = false;

            if (bHadValue)
            {
                if (V != dLastValue)
                {
                    switch (_status)
                    {
                        case Status.stUp:
                            {
                                if (V > dLastValue)
                                {
                                    V2 = V;
                                    V3 = V;
                                }
                                else
                                {
                                    V3 = V;
                                    if (V2 - V1 > dSeed) { _status = Status.stDown; } else { _status = Status.stNone; }
                                }
                                break;
                            }
                        case Status.stDown:
                            {
                                if (V < dLastValue) { V3 = V; } else { _status = Status.stNone; }
                                if (V2 - V3 > dSeed)
                                {
                                    ret = true;
                                    _iCount++;
                                    _status = Status.stNone;
                                }
                                break;
                            }
                        default:
                            {
                                if (V > dLastValue)
                                {
                                    V1 = V;
                                    V2 = V;
                                    V3 = V;
                                    _status = Status.stUp;
                                }
                                break;
                            }
                    }
                    dLastValue = V;
                }
            }
            else { bHadValue = true; }

            return ret;
        }
        public void Reset()
        {
            _status = Status.stNone;
            dLastValue = 0;
            _iCount = 0;
            V1 = 0;
            V2 = 0;
            V3 = 0;
        }
        public int iCount
        {
            get { return _iCount; }
        }
    }
}